<template>
	<div class="sceditor">
		<Editor v-model="contentValue" :init="init" :disabled="disabled" :placeholder="placeholder"
			@onClick="onClick" />
	</div>
</template>

<script>
	import API from "@/api";
	import Editor from '@tinymce/tinymce-vue'
	import tinymce from 'tinymce/tinymce'
	import 'tinymce/themes/silver'
	import 'tinymce/icons/default'
	import 'tinymce/models/dom'

	// 引入编辑器插件
	import 'tinymce/plugins/code' //编辑源码
	import 'tinymce/plugins/image' //插入编辑图片
	import 'tinymce/plugins/media' //插入视频
	import 'tinymce/plugins/link' //超链接
	import 'tinymce/plugins/preview' //预览
	import 'tinymce/plugins/template' //模板
	import 'tinymce/plugins/table' //表格
	import 'tinymce/plugins/pagebreak' //分页
	import 'tinymce/plugins/lists' //列
	import 'tinymce/plugins/advlist' //列
	import 'tinymce/plugins/quickbars' //快速工具条

	export default {
		name: 'scEditor',
		components: {
			Editor
		},
		props: {
			modelValue: {
				type: String,
				default: ""
			},
			placeholder: {
				type: String,
				default: ""
			},
			height: {
				type: Number,
				default: 300,
			},
			disabled: {
				type: Boolean,
				default: false
			},
			plugins: {
				type: [String, Array],
				default: 'code image media link preview table quickbars template pagebreak lists advlist'
			},
			toolbar: {
				type: [String, Array],
				default: 'insertMiniprogram | undo redo | forecolor backcolor bold italic underline strikethrough link | blocks fontfamily fontsize | \
					alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | pagebreak | \
					image media table template preview | code selectall'
			},
			templates: {
				type: Array,
				default: () => []
			},
			options: {
				type: Object,
				default: () => {}
			}
		},
		data() {
			return {
				init: {
					language_url: './tinymce/langs/zh_CN.js',
					language: 'zh_CN',
					skin_url: './tinymce/skins/ui/oxide',
					content_css: "./tinymce/skins/content/default/content.css",
					menubar: false,
					statusbar: true,
					plugins: this.plugins,
					toolbar: this.toolbar,
					toolbar_mode: 'sliding',
					font_size_formats: '12px 14px 16px 18px 22px 24px 36px 72px',
					height: this.height,
					placeholder: this.placeholder,
					branding: false,
					resize: true,
					elementpath: true,
					content_style: "",
					templates: this.templates,
					quickbars_selection_toolbar: 'forecolor backcolor bold italic underline strikethrough link',
					quickbars_image_toolbar: 'alignleft aligncenter alignright',
					quickbars_insert_toolbar: false,
					image_caption: true,
					image_advtab: true,
					convert_urls: false,
					images_upload_handler: function(blobInfo) {
						return new Promise((resolve, reject) => {
							API.system.upload.token.get().then(oss => {
								var rand = function(length) {
									let result = '';
									const characters =
										'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
									const charactersLength = characters.length;
									for (let i = 0; i < length; i++) {
										result += characters.charAt(Math.floor(Math.random() *
											charactersLength));
									}
									return result;
								}
								var cfg = {
									key: `${oss.data.dir}${rand(16)}_${blobInfo.filename()}`,
									policy: oss.data.policy,
									OSSAccessKeyId: oss.data.accessid,
									success_action_status: '200',
									callback: oss.data.callback,
									signature: oss.data.signature,
								}
								API.common.upload.url = oss.data.host;
								const data = new FormData();
								for (const key in cfg) {
									data.append(key, cfg[key]);
								}
								data.append("file", blobInfo.blob(), blobInfo.filename());
								API.common.upload.post(data).then((res) => {
									resolve(res.data.src)
								}).catch(() => {
									reject("Image upload failed")
								})
							});
						})
					},
					setup: function(editor) {
						editor.on('init', function() {
							this.getBody().style.fontSize = '14px';
						})
						editor.on('OpenWindow', function(e) {
							//FIX 编辑器在el-drawer中，编辑器的弹框无法获得焦点
							var D = document.querySelector('.el-drawer.open')
							var E = e.target.editorContainer
							if (D && D.contains(E)) {
								var nowDA = document.activeElement
								setTimeout(() => {
									document.activeElement.blur()
									nowDA.focus()
								}, 0)
							}
						})

						// 注册名为"insertMiniprogram"的按钮
						editor.ui.registry.addButton('insertMiniprogram', {
							text: '插入小程序', // 按钮文字
							icon: 'link', // 可选图标
							onAction: function() {
								// 打开弹窗
								editor.windowManager.open({
									title: '插入小程序链接',
									body: {
										type: 'panel',
										items: [{
												type: 'input',
												name: 'text',
												label: '链接文本',
												placeholder: '请输入链接显示文本'
											},
											{
												type: 'input',
												name: 'appid',
												label: '小程序AppID',
												placeholder: '例: wxa2ba44d4189592d2',
											},
											{
												type: 'input',
												name: 'path',
												label: '小程序路径',
												placeholder: '例: /pages/index/index',
											}
										]
									},
									initialData: {
										text: "点击打开小程序",
										appid: 'wxa2ba44d4189592d2',
										path: '/pages/index/index'
									},
									buttons: [{
											type: 'cancel',
											text: '取消'
										},
										{
											type: 'submit',
											text: '插入',
											primary: true
										}
									],
									onSubmit: function(api) {
										const data = api.getData();
										// 生成 HTML 代码
										const html = `<a href="#"
						                            data-miniprogram-appid="${data.appid}"
						                            data-miniprogram-path="${data.path}"
						                            style="color: blue; text-decoration: underline;">
						                            ${data.text || '小程序链接'}
						                        </a>`;
										editor.insertContent(html);
										api.close();
									}
								});
							}
						});
					},
					...this.options
				},
				contentValue: this.modelValue
			}
		},
		watch: {
			modelValue(val) {
				this.contentValue = val
			},
			contentValue(val) {
				this.$emit('update:modelValue', val);
			}
		},
		mounted() {
			tinymce.init({})
		},
		methods: {
			onClick(e) {
				this.$emit('onClick', e, tinymce)
			}
		}
	}
</script>

<style>
</style>
